`timescale 1ns / 1ps
module Async_port(
/*********NAND flash Async mode Port*********/
    output      WE_s,  
    output      RE_s,   
    output      CLE,    
    output      ALE,   
    inout[7:0]  DQ,
    input       RB,     
/***********Mode control port**************/
    input       clkX2,
    input       dclk,
    input       rst_n,
    input       isEDO,
    input       en,         //port module enable
    input[2:0]  Cmd,  //
    input[7:0]  InputVal,       //
    output      IV_En,
    output[7:0] ReadVal,
    output      RV_En,
    input[31:0] RWDataNum,
    input[31:0] RWDataCounter
);

parameter State_command =   3'b000;
parameter State_adderss =   3'b001;
parameter State_WriteData = 3'b010;
parameter State_ReadData  = 3'b011;
parameter State_Idle =      3'b100;
parameter State_WriteWait = 3'b111;

parameter Idle =      4'b1111;
parameter WriteWait = 4'b0000;
parameter Command =   4'b0001;
parameter WriteData = 4'b0010;
parameter ReadData =  4'b0100;
parameter Address =   4'b1000;

wire clk_m;
reg[2:0] cur_state;
reg cle_r;
reg ale_r;
reg we_en;
reg re_en;
wire[7:0] dq_i;
reg [7:0] dq_o;
reg [7:0] read_reg;
reg out_data_vaild;

assign ReadVal = en ? read_reg : 8'hzz;
assign RV_En = en ? out_data_vaild : 1'bz;
assign clk_m = clkX2;
assign CLE = en ? cle_r : 1'bz;
assign ALE = en ? ale_r : 1'bz;
assign dq_i = DQ;
assign DQ = en ? dq_o : 8'hzz;//(en & we_en) ? dq_o : 8'hzz;
assign WE_s = en ? (we_en ? dclk : 1'b1) : 1'bz;
assign RE_s = en ? (re_en ? dclk : 1'b1) : 1'bz;
assign IV_En = en ? dclk : 1'hz;

always @(negedge dclk or negedge rst_n) begin
    if (rst_n) begin
        case (Cmd)
           State_adderss : begin
               cle_r <= 0;
               ale_r <= 1;
           end
           State_command : begin
               cle_r <= 1;
               ale_r <= 0;
           end
           State_Idle : begin
               cle_r <= 0;
               ale_r <= 0;
           end
           State_ReadData : begin
               cle_r <= 0;
               ale_r <= 0;
           end
           State_WriteData : begin
               cle_r <= 0;
               ale_r <= 0;
           end
           State_WriteWait : begin
               cle_r <= 0;
               ale_r <= 0;
           end
            default: begin
               cle_r <= 0;
               ale_r <= 0;
            end
        endcase
    end else begin
        
    end
end

always @(negedge dclk ) begin
    if (Cmd === State_adderss || Cmd === State_command || Cmd === State_WriteData || Cmd === WriteWait) begin
        dq_o <= InputVal;
        we_en <= 1;
    end else if (Cmd === State_ReadData) begin
        dq_o <= 8'hzz;
        we_en <= 0;
    end else begin
        dq_o <= dq_o;
        we_en <= 0;            
    end
end

always @(negedge dclk) begin
    if (Cmd === State_ReadData) begin
        re_en <= 1;
    end else begin
        re_en <= 0;
    end
end

reg read_start;
always @(posedge dclk) begin
    if (Cmd === State_ReadData) begin
        read_reg <= dq_i;
        read_start <= 1'b1;
    end else begin
        read_reg <= read_reg;
        read_start <= 1'b0;
    end
end

always @(negedge clk_m or negedge rst_n) begin
    if (rst_n & Cmd === State_ReadData & read_start) begin
        out_data_vaild <= ~out_data_vaild;
    end else begin
        out_data_vaild <= 1'b0;
    end
end

endmodule // Async_port